﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SurfaceCardsBoardLibrary.Interfaces;
using System.Windows;
using SurfaceCardsBoardLibrary;
using SurfaceCardsGameKit.Tools;

namespace SurfaceCardsGameKit.Dispositions
{
    class HeapDisposition : IDisposition
    {

        public double AngleRandom { get; set; }
        public Point CenterRandom { get; set; }

        private Random _random;

        public HeapDisposition()
        {
            AngleRandom = 20;
            CenterRandom = new Point(20, 20);
            _random = new Random();

        }

        #region IDisposition Members

        public void Render(IDeck deck, Size cardSize, Rect destinationRect, Point center, double deckOrientation,
            bool useTransitions, bool sizeChanged, DeckOrientation deckupDownOrientation, double durationRatio)
        {
            Point deckMiddle = new Point(destinationRect.X + destinationRect.Width / 2, destinationRect.Y + destinationRect.Height / 2);
            DispositionOffset offset;

            foreach (var card in deck)
            {
                if (card.ScatterViewItem.Visibility == Visibility.Collapsed)
                    continue;

                var svi = card.ScatterViewItem;

                // calc disposition if it's needed
                Card c = card as Card;
                if (c != null && sizeChanged && !c.HeapDispositionOffset.HasValue)
                {
                    // calculate new random value
                    offset = CalculateNewOffset(c);
                }
                else if (c != null && c.HeapDispositionOffset.HasValue)
                    offset = c.HeapDispositionOffset.Value;
                else
                    offset = CalculateNewOffset(card);

                // save the offset in the card
                c.HeapDispositionOffset = offset;

                // use Deck width & Height & Orientation
                offset.Center = new Point(deckMiddle.X + offset.Center.X, deckMiddle.Y + offset.Center.Y);
                offset.Orientation = (offset.Orientation + deckOrientation) % 360;

                // handle isSelected
                if (card.IsSelected)
                    offset.Center = new Point(offset.Center.X,
                        deckupDownOrientation == DeckOrientation.Up ? offset.Center.Y + -20 : offset.Center.Y + 20);

                // Translate point 
                offset.Center = deck.ScatterViewItem.TranslatePoint(offset.Center, deck.ScatterView);

                bool centerChanged = sizeChanged || svi.Center != offset.Center;

                if (useTransitions)
                {
                    // calc orientation
                    if (sizeChanged)
                        offset.Orientation = DispositionHelper.CalcOrientationForCards(svi.ActualOrientation, offset.Orientation);
                    else
                        offset.Orientation = svi.ActualOrientation;

                    bool orientationChanged = svi.ActualOrientation != offset.Orientation;

                    var duration = DispositionHelper.ComputeAnimationDuration(
                        svi.ActualCenter, offset.Center, svi.ActualOrientation, offset.Orientation, durationRatio);

                    // center animation
                    if (centerChanged)
                        DispositionHelper.BeginCenterAnimation(svi, offset.Center, duration);

                    // orientation animation
                    if (orientationChanged)
                        DispositionHelper.BeginOrientationAnimation(svi, offset.Orientation, duration);
                }
                else
                {
                    double orientation = offset.Orientation;
                    bool orientationChanged = svi.Orientation != orientation;

                    if (centerChanged)
                    {
                        DispositionHelper.StopCenterAnimation(svi);
                        card.Center = offset.Center;
                    }
                    if (orientationChanged)
                    {
                        DispositionHelper.StopOrientationAnimation(svi);
                        card.Orientation = orientation;
                    }
                }
            }

        }

        public bool CanApplyDisposition(Size cardSize, Rect destinationRect, int cardsCount)
        {
            return true;
        }

        private DispositionOffset CalculateNewOffset(ICard card)
        {
            DispositionOffset offset = new DispositionOffset();

            var center = new Point(0, 0);

            center.X += (_random.NextDouble() - .5) * 2 * CenterRandom.X;
            center.Y += (_random.NextDouble() - .5) * 2 * CenterRandom.Y;

            offset.Center = center;

            offset.Orientation = card.Orientation + (_random.NextDouble() - .5) * 2 * AngleRandom;

            return offset;
        }

        #endregion
    }
}
